package com.knife.file.app.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.knife.common.constants.BaseConstants;
import com.knife.common.exception.CommonException;
import com.knife.common.utils.KnifeEncryptionUtils;
import com.knife.file.app.KnifeFileInfoService;
import com.knife.file.domain.entity.KnifeFileInfo;
import com.knife.file.domain.service.KnifeStoreService;
import com.knife.file.domain.service.factory.KnifeStoreFactory;
import com.knife.file.infra.constants.FileConstant;
import com.knife.file.infra.mapper.KnifeFileInfoMapper;
import com.knife.file.infra.utils.CodeUtils;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 业务文件服务
 *
 * @author： 76875
 * @date： 2022/4/7 星期四 16:02
 * @description：
 * @modifiedBy：
 * @version: 1.0
 */
@Service
public class KnifeFileInfoServiceImpl implements KnifeFileInfoService {

    @Autowired
    private KnifeStoreFactory knifeStoreFactory;

    @Resource
    private KnifeFileInfoMapper knifeFileInfoMapper;

    @Override
    public KnifeFileInfo uploadMultipart(Long tenantId, String bucketName, String attachmentUuid, String directory, String fileName, Integer docType, String storageCode, MultipartFile multipartFile) {
        if (StringUtils.isEmpty(fileName)){
            fileName = multipartFile.getOriginalFilename();
        }
        CodeUtils.checkFileName(fileName);
        try(InputStream inputStream = multipartFile.getInputStream()){
            KnifeFileInfo knifeFileInfo = KnifeFileInfo.builder().bucketName(bucketName)
                    .directory(directory)
                    .fileName(fileName)
                    .fileType(BaseConstants.Flag.YES.equals(docType) ? FileConstant.KnifeFileConstant.DEFAULT_MULTI_TYPE : multipartFile.getContentType())
                    .fileSize(multipartFile.getSize())
                    .tenantId(tenantId)
                    .storageCode(storageCode)
                    .attachmentUuid(StringUtils.isBlank(attachmentUuid) ? FileConstant.KnifeFileConstant.DEFAULT_ATTACHMENT_UUID : attachmentUuid)
                    // 再获取一份流，避免因为获取md5加密导致上传文件失败
                    .md5(KnifeEncryptionUtils.MD5.encrypt(multipartFile.getInputStream()))
                    .build();
            KnifeStoreService knifeStoreService = knifeStoreFactory.build(tenantId, storageCode);
            return knifeStoreService.uploadFile(knifeFileInfo,inputStream);
        }catch (IOException e){
            throw new CommonException(e.getMessage());
        }
    }

    @Override
    public KnifeFileInfo uploadFile(Long tenantId, String bucketName, String attachmentUuid, String directory, String fileName, Integer docType, String storageCode,String filePath) {
        Path path = Paths.get(filePath);
        File file = path.toFile();
        if (StringUtils.isEmpty(fileName)){
            fileName = file.getName();
        }
        CodeUtils.checkFileName(fileName);
        try(InputStream inputStream = new FileInputStream(file);
            BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream)){
            String contentType = Files.probeContentType(path);
            KnifeFileInfo knifeFileInfo = KnifeFileInfo.builder().bucketName(bucketName)
                    .directory(directory)
                    .fileName(fileName)
                    .fileType(BaseConstants.Flag.YES.equals(docType) ? FileConstant.KnifeFileConstant.DEFAULT_MULTI_TYPE : contentType)
                    .fileSize(file.length())
                    .tenantId(tenantId)
                    .storageCode(storageCode)
                    .attachmentUuid(StringUtils.isBlank(attachmentUuid) ? FileConstant.KnifeFileConstant.DEFAULT_ATTACHMENT_UUID : attachmentUuid)
                    // 再获取一份流，避免因为获取md5加密导致上传文件失败
                    .md5(KnifeEncryptionUtils.MD5.encrypt(bufferedInputStream))
                    .build();
            KnifeStoreService knifeStoreService = knifeStoreFactory.build(tenantId, storageCode);
            return knifeStoreService.uploadFile(knifeFileInfo,filePath);
        }catch (IOException e){
            throw new CommonException(e.getMessage());
        }
    }

    @Override
    public List<String> selectUrls(List<Long> fileIdList, Long tenantId) {
        QueryWrapper<KnifeFileInfo> qw = new QueryWrapper<>();
        qw.in("id",fileIdList);
        // 此处使用了mp的租户插件，所以暂不添加租户id条件
        List<KnifeFileInfo> knifeFileInfos = knifeFileInfoMapper.selectList(qw);
        if (CollectionUtils.isNotEmpty(knifeFileInfos)){
            return knifeFileInfos.stream().map(KnifeFileInfo::getFileUrl).collect(Collectors.toList());
        }
        return null;
    }
}
